package org.hs.phd.common.simpleplayer.frameviewer;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.swing.JComponent;

import org.hs.phd.common.simpleplayer.ImageSequenceFrame;
import org.hs.phd.common.simpleplayer.Overlay;
import org.hs.phd.common.simpleplayer.PlayerViewerLayer;

public class ViewerCanvas extends JComponent implements MouseListener, MouseMotionListener {

	private static final Dimension DEFAULT_PREFERRED_DIMS = new Dimension(800, 650);

	private static final long serialVersionUID = 1L;

	private final FrameViewer viewer;

	private List<PlayerViewerLayer> layers;

	private Dimension preferredDimension;
	private float scale;

	private BufferedImage image;
	private Collection<Overlay> overlays;

	private ImageSequenceFrame frame;

	public ViewerCanvas(FrameViewer viewer) {
		this.viewer = viewer;
		this.setScale(1);
		layers = new ArrayList<PlayerViewerLayer>();
		preferredDimension = DEFAULT_PREFERRED_DIMS;
		addMouseListener(this);
		addMouseMotionListener(this);
		setDoubleBuffered(true);
	}

	public void addLayer(PlayerViewerLayer layer) {
		layers.add(layer);
	}

	public void setImage(ImageSequenceFrame frame) {

		//as an optimization we avoid getBufferedImage() if frame is the same
		if( this.frame != frame ){
			this.frame = frame;
			this.image = frame.getFrameImage().getBufferedImage();
		}
		
		this.overlays = frame.getOverlays();
		
		refreshUI();
	}

	private void refreshUI() {
		if(image != null){
			preferredDimension = new Dimension(Math.round(scale*image.getWidth()), Math.round(scale*image.getHeight()));
		}else{
			preferredDimension = DEFAULT_PREFERRED_DIMS;
		}

//		invalidate();
//		Container parent = getParent();
//		if( parent != null ){
//			parent.validate();
//		}
		repaint();
	}
	
	@Override
	public void paint(Graphics g) {
		

		if( image != null ){
			Graphics2D g2ScaledCopy = (Graphics2D) g.create();
			g2ScaledCopy.scale(scale, scale);

			g2ScaledCopy.drawImage(image, 0, 0, Math.round(image.getWidth()), Math.round(image.getHeight()), null);
			for( Overlay overlay : overlays ){
				overlay.paint(g2ScaledCopy);
			}
			
			g2ScaledCopy.dispose();
		}
		
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.paint(g);
			}
		}
	}
	
	@Override
	public Dimension getPreferredSize() {
		return preferredDimension;
	}

	public float getScale() {
		return scale;
	}

	public final void setScale(float scale) {
		this.scale = scale;
		repaint();
		updateUI();
	}
	
	public Point viewToModel(int x, int y) {
		return new Point(Math.round(x/scale),Math.round(y/scale) );
	}

	public Point modelToView(int x, int y) {
		return new Point(Math.round(x*scale),Math.round(y*scale) );
	}

	@Override
	public void mouseDragged(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mouseDragged(e);
			}
		}
	}

	@Override
	public void mouseMoved(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mouseMoved(e);
			}
		}
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mouseClicked(e);
			}
		}
	}

	@Override
	public void mousePressed(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mousePressed(e);
			}
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mouseReleased(e);
			}
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mouseEntered(e);
			}
		}
	}

	@Override
	public void mouseExited(MouseEvent e) {
		for( PlayerViewerLayer layer : layers ){
			if( layer.isEnabled() ){
				layer.mouseExited(e);
			}
		}
	}



}
